package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.*;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.fee.FeeValueVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.tomcat.util.buf.UDecoder;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liubo
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
        implements ApartmentInfoService {
@Autowired
private GraphInfoService graphInfoService;
@Autowired
private ApartmentFacilityService apartmentFacilityService;
@Autowired
private ApartmentLabelService apartmentLabelService;
@Autowired
private ApartmentFeeValueService apartmentFeeValueService;

@Autowired
private ApartmentInfoMapper apartmentInfoMapper;

@Autowired
private GraphInfoMapper graphInfoMapper;
@Autowired
private FacilityInfoMapper facilityInfoMapper;
@Autowired
private LabelInfoMapper labelInfoMapper;
@Autowired
private FeeValueMapper feeValueMapper;
@Autowired
private RoomInfoService roomInfoService;
@Autowired
private DistrictInfoService districtInfoService;
@Autowired
private CityInfoService cityInfoService;
@Autowired
private ProvinceInfoService provinceInfoService;

    @Override
    public void customsaveOrUpdate(ApartmentSubmitVo apartmentSubmitVo) {
//        1.先判定下id是否为空来确定是更新还是保存.不能先保存公寓信息表因为会把id主键回显,这样id就一定有值,
//        就会一直走更新
        boolean q = apartmentSubmitVo.getId() != null;
//        2.保存或更新公寓信息(单表),因为是单表所以直接用saveorupdate就可以,放在这里的原因是方便下面会用到主键,
//        其实也可以不放到这里,放到保存操作的部分也可以,因为第三步的删除一定能会有id存在, 但是最后的保存需要用到主键,
//        所以只要第二步在保存之前就行.因为apartmentSubmitVo继承了apartmentInfo,所以有公寓表的全部属性,
//        利用saveorupdate,会把apartmentSubmitVo里属于apartmentInfo的属性自动保存在公寓信息表
        saveOrUpdate(apartmentSubmitVo);
        Long id = apartmentSubmitVo.getId();
        apartmentSubmitVo.setProvinceName(provinceInfoService.getById(apartmentSubmitVo.getProvinceId()).getName());
        apartmentSubmitVo.setDistrictName(districtInfoService.getById(apartmentSubmitVo.getDistrictId()).getName());
        apartmentSubmitVo.setCityName(cityInfoService.getById(apartmentSubmitVo.getCityId()).getName());
        saveOrUpdate(apartmentSubmitVo);

        //3.判段第一步q的结果,若为true,则为更新(删除+新增).
        if (q){
            //删除图片,根据itemType和itemId(包含公寓Id和房间Id,所以需要指定)来删除,前端是通过graphvo传递给后台的
            // (前端传的图片和公寓没有任何关联,传递到后台,需要靠手动添加type和id,graphvo自带的两个属性name和url,把这四个属性封装到graphInfo实体类里,然后插入到数据库中.),里面只有name和url,而后台操作数据库是根据graphInfo的,
            // 所以这里放实体需要放graphinfo;
            LambdaQueryWrapper<GraphInfo> a = new LambdaQueryWrapper<>();
            a.eq(GraphInfo::getItemType,ItemType.APARTMENT);
            a.eq(GraphInfo::getItemId,apartmentSubmitVo.getId());
            graphInfoService.remove(a);

            //删除配套
            LambdaQueryWrapper<ApartmentFacility> b = new LambdaQueryWrapper<>();
            b.eq(ApartmentFacility::getApartmentId,apartmentSubmitVo.getId());
            apartmentFacilityService.remove(b);

            //删除标签
            LambdaQueryWrapper<ApartmentLabel> c = new LambdaQueryWrapper<>();
            c.eq(ApartmentLabel::getApartmentId,apartmentSubmitVo.getId());
            apartmentLabelService.remove(c);

            //删除杂费值
            LambdaQueryWrapper<ApartmentFeeValue> d = new LambdaQueryWrapper<>();
            d.eq(ApartmentFeeValue::getApartmentId,apartmentSubmitVo.getId());
            apartmentFeeValueService.remove(d);

        }

        //4.保存(无论如何[更新和保存]都会走保存)
        //保存图片(需要先判定前端是否传过来图片,再去保存)
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        if (!CollectionUtils.isEmpty(graphVoList)){
            List<GraphInfo> graphInfoList = new ArrayList<>(graphVoList.size());
            for (GraphVo graphVo : graphVoList) {
                GraphInfo graphInfo = GraphInfo.builder().name(graphVo.getName()).url(graphVo.getUrl())
                        .itemType(ItemType.APARTMENT).itemId(apartmentSubmitVo.getId()).build();
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }

        //保存配套id
        List<Long> facilityInfoIds = apartmentSubmitVo.getFacilityInfoIds();
        if (!CollectionUtils.isEmpty(facilityInfoIds)){
            List<ApartmentFacility> apartmentFacilityList = new ArrayList<>(facilityInfoIds.size());
            for (Long facilityInfoId : facilityInfoIds) {
                ApartmentFacility apartmentFacility = ApartmentFacility.builder().apartmentId(apartmentSubmitVo.getId())
                        .facilityId(facilityInfoId).build();
                apartmentFacilityList.add(apartmentFacility);
            }
            apartmentFacilityService.saveBatch(apartmentFacilityList);

            //保存标签
            List<Long> labelIds = apartmentSubmitVo.getLabelIds();
            if (!CollectionUtils.isEmpty(labelIds)){
                List<ApartmentLabel> apartLableList = new ArrayList<>(labelIds.size());
                for (Long labelId : labelIds) {
                    ApartmentLabel apartmentLabel = ApartmentLabel.builder().apartmentId(apartmentSubmitVo.getId()).labelId(labelId)
                            .build();
                    apartLableList.add(apartmentLabel);
                }
                apartmentLabelService.saveBatch(apartLableList);
            }

            //保存杂费值
            List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
            if (!CollectionUtils.isEmpty(feeValueIds)){
                List<ApartmentFeeValue> apartmentFeeList = new ArrayList<>(feeValueIds.size());
                for (Long feeValueId : feeValueIds) {
                    ApartmentFeeValue apartmentFeeValue = ApartmentFeeValue.builder().apartmentId(apartmentSubmitVo.getId()).feeValueId(feeValueId)
                            .build();
                    apartmentFeeList.add(apartmentFeeValue);
                }
                apartmentFeeValueService.saveBatch(apartmentFeeList);
            }

        }
    }



    @Override
    public void queryPage(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
        apartmentInfoMapper.queryPage(page,queryVo);
    }

    @Override
    public ApartmentDetailVo queryDetailById(Long id) {
        //1.查询公寓单表信息
        ApartmentInfo apartmentInfo = getById(id);
        if (apartmentInfo==null){
            return null;
        }
        //2.查询图片信息
        //自定义mapper层的方法,在数据库中查询graphInfo表然后只查关于GraphVo的name和url,然后最后就会自动映射到graphVo实体类中.
        List<GraphVo> graphVoList = graphInfoMapper.queryByItemId(id,ItemType.APARTMENT);

        //3.查询配套信息
        List<FacilityInfo> facilityInfoList = facilityInfoMapper.queryByApartmentId(id);

        //4.查询标签信息
        List<LabelInfo> labelInfoList = labelInfoMapper.queryByApartmentId(id);

        //5.查询杂费值
        //通过中间表的公寓id,查出杂费值id集合,然后把杂费值表和杂费key表做一个内连接(子表有数据,主表就一定有数据)
        //接着后面加个in 把杂费值id集合放后面,select后面要看FeeValueVo要什么属性,就写什么属性,名字要对的上,驼峰模式.
        List<FeeValueVo> feeValueVoList = feeValueMapper.queryByApartmentId(id);

        //把以上合并到ApartmentDetailVo
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        BeanUtils.copyProperties(apartmentInfo,apartmentDetailVo);
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        apartmentDetailVo.setFeeValueVoList(feeValueVoList);
        apartmentDetailVo.setGraphVoList(graphVoList);
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        return apartmentDetailVo;

    }

    @Override
    public void customRemoveById(Long id) {
        //1.先判断公寓里是否有房间(通过房间信息表里的公寓Id所包含的房间Id来判断),如果有就返回一个自定义异常(带枚举),后面删除部分都不走了,
        // 走全局异常处理.
        LambdaQueryWrapper<RoomInfo> q = new LambdaQueryWrapper<>();
        q.eq(RoomInfo::getApartmentId,id);
        long count = roomInfoService.count(q);
        if (count>0){
            throw new LeaseException(ResultCodeEnum.DELETE_ERROR);
        }
        removeById(id);

        //2.删除图片
        LambdaQueryWrapper<GraphInfo> a = new LambdaQueryWrapper<>();
        a.eq(GraphInfo::getItemId,id);
        a.eq(GraphInfo::getItemType,ItemType.APARTMENT);
        graphInfoService.remove(a);

        //3.删除配套
        LambdaQueryWrapper<ApartmentFacility> b = new LambdaQueryWrapper<>();
        b.eq(ApartmentFacility::getApartmentId,id);
        apartmentFacilityService.remove(b);

        //4.删除标签
        LambdaQueryWrapper<ApartmentLabel> c = new LambdaQueryWrapper<>();
        c.eq(ApartmentLabel::getApartmentId, id);
        apartmentLabelService.remove(c);

        //5.删除杂费值
        LambdaQueryWrapper<ApartmentFeeValue> d = new LambdaQueryWrapper<>();
        d.eq(ApartmentFeeValue::getApartmentId,id);
        apartmentFeeValueService.remove(d);

    }
}




